/*
 * Copyright (c) 2024, Qi Yaolong.
 * dragon@hbu.edu.cn
 * HeBei University, China.
 * 
 * 简体中文
 * 保留所有权利。除非符合（遵守）以下条款，否则您不得使用此文件：
 * 
 * 禁止任何未经授权的个人或组织以任何形式将本程序及其附属资料、创新、创意、架构设计、算法、衍生作品
 * 等用于任何商业目的、盈利活动、各类竞赛(比赛)、直播教学、录播教学、线下课程、书籍编写、教材编写、
 * 会议、培训、公益活动、项目课题、毕业设计、毕业论文、学术论文等。
 * 
 * 本程序由版权持有人和贡献人“按原样”提供，不提供任何明示或暗示担保，包括但不局限于对适销性和特定
 * 用途适合性的暗示担保。在任何情况下，版权持有人或贡献人对因使用本程序而导致的任何直接、间接、附带、
 * 特殊、典型或后果性损害（包括但不限于购买替代商品或服务；使用损失、数据丢失或利润损失；业务中断）
 * 不承担任何责任，无论其如何产生，也不论其责任理论为何，无论是合同、严格责任还是侵权（包括疏忽或
 * 其他），即使已告知此类损害的可能性。
 * 
 * English
 * All rights reserved. You may NOT use this file except in compliance with the
 * following terms:
 * 
 * IT IS PROHIBITED FOR ANY UNAUTHORIZED PERSON OR ENTITY TO USE THIS PROGRAM AND 
 * ITS ANCILLARY DATA, INNOVATIONS, CONCEPTS, ARCHITECTURE DESIGN, ALGORITHMS, 
 * DERIVED WORKS, ETC., IN ANY FORM FOR COMMERCIAL PURPOSES, PROFIT-MAKING 
 * ACTIVITIES, VARIOUS COMPETITIONS (CONTESTS), LIVE TEACHING, PRE-RECORDED 
 * LESSONS, OFFLINE COURSES, BOOK WRITING, CONFERENCES, TRAININGS, PUBLIC WELFARE 
 * ACTIVITIES, PROJECTS, TOPICS, GRADUATION DESIGNS, DISSERTATIONS, THESES, AND 
 * OTHER APPLICATIONS.
 * 
 * THIS PROGRAM IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS PROGRAM, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "../global_settings.h" 
#include "httpd.h"              
#include "param_nv.h"
#include "sle_client.h"
#include "sle_server_adv.h"

uint8_t hex_val(char hex)
{
    if ((hex >= '0') && (hex <= '9'))
        return (hex - '0');
    else if ((hex >= 'a') && (hex <= 'f'))
        return (hex - 'a' + 10);
    else if ((hex >= 'A') && (hex <= 'F'))
        return (hex - 'A' + 10);

    return 0;
}

int str2hex(char *str, int len, uint8_t buf[])
{
    int i;
    int sz, j;
    char *p;

    p = str;
    if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
        p += 2;

    sz = len >> 1;
    j = 0;
    
    for (i = 0; i < sz; i++)
    {
        buf[i] = (hex_val(p[j++]) << 4);
        buf[i] |= hex_val(p[j++]);
    }

    return sz;
}

int hex2str(uint8_t *buf, int len, char *prefix, char *str)
{
    int i, j;
    unsigned char b;

    j = 0;
    if (prefix != NULL)
    {
        strcpy(str, prefix);
        j = strlen(prefix);
    }

    for (i = 0; i < len; i++)
    {
        b = buf[i] >> 4;
        if (b <= 9)
            str[j++] = '0' + b;
        else
        {
            str[j++] = 'a' + b - 10;
        }

        b = buf[i] & 0x0f;
        if (b <= 9)
            str[j++] = '0' + b;
        else
        {
            str[j++] = 'a' + b - 10;
        }
    }

    str[j] = 0;

    return j;
}

int urldecode(char *s)
{
    int i = 0;
    int j = 0;
    int k;

    while (s[i] != '\0')
    {
        if (s[i] == '%' && isxdigit(s[i + 1]) && isxdigit(s[i + 2]))
        {
            for (k = 1; k <= 2; k++)
            {
                if (k == 1)
                    s[j] = 0;
                else
                    s[j] <<= 4;
                if (s[i + k] >= '0' && s[i + k] <= '9')
                    s[j] |= s[i + k] - '0';
                else if (s[i + k] >= 'a' && s[i + k] <= 'f')
                    s[j] |= s[i + k] - 'a' + 10;
                else if (s[i + k] >= 'A' && s[i + k] <= 'F')
                    s[j] |= s[i + k] - 'A' + 10;
            }
            i += 3;
        }
        else
        {
            if (s[i] == '+')
                s[j] = ' ';
            else
                s[j] = s[i];
            i++;
        }
        j++;
    }
    s[j] = '\0';
    return j;
}

char *urlencode(const char *s)
{
    char *p;
    int size = 0;

    urlencode_buf((char *)s, &size);
    p = mem_malloc(size);
    if (p != NULL)
    {
        if (s != NULL)
            strcpy(p, s);
        else
            *p = '\0';
        urlencode_buf(p, &size);
    }
    return p;
}

int urlencode_buf(char *buf, int *bufsize)
{
    char x;
    int i, j, len;

    if (buf == NULL)
    {
        *bufsize = 1;
        return -1;
    }

    len = 0;
    for (i = 0; buf[i] != '\0'; i++)
    {
        if (isalnum(buf[i]) || strchr(" -_.", buf[i]) != NULL)
            len++;
        else
            len += 3;
    }
    if (*bufsize < len + 1)
    {
        if (len >= i)
            *bufsize = len + 1;
        else
            *bufsize = i + 1;
        return -1;
    }

    j = len - 1;
    for (i--; i >= 0; i--)
    {
        if (isalnum(buf[i]) || strchr("-_.", buf[i]) != NULL)
        {
            buf[j] = buf[i];
            j--;
        }
        else if (buf[i] == ' ')
        {
            buf[j] = '+';
            j--;
        }
        else
        {
            x = buf[i] & 15;
            buf[j] = (x < 10) ? (x + '0') : (x - 10 + 'A');
            x = (buf[i] >> 4) & 15;
            buf[j - 1] = (x < 10) ? (x + '0') : (x - 10 + 'A');
            buf[j - 2] = '%';
            j -= 3;
        }
    }
    buf[len] = '\0';
    return len;
}

int8_t httpd_post_begin(void *connection, const char *uri, const char *http_request,
                        uint16_t http_request_len, int content_len, char *response_uri,
                        uint16_t response_uri_len, uint8_t *post_auto_wnd)
{
#if MODE_DEBUG
    printf("uri: %s\r\n", uri);
    printf("http_request: %s\r\n", http_request);
    printf("http_request_len: %d\r\n", http_request_len);
    printf("content_len: %d\r\n", content_len);
#endif

    return ERR_OK;
}

int8_t httpd_post_receive_data(void *connection, struct pbuf *p)
{
#if MODE_DEBUG
    printf("p->len: %d\r\n", p->len);
    printf("p->tot_len: %d\r\n", p->tot_len);
    printf("p->next: %p\r\n", p->next);
    printf("p->payload: %s\r\n", p->payload);
#endif

    char *payload = (char *)p->payload;

    payload[p->len] = '\0';

    urldecode(payload);

    char lname[20] = {0};
    if (httpd_post_parse(payload, "lname", lname) == 0)
    {
        printf("local name: %s\r\n", lname);
        sle_set_announce_name(lname);                               
        uapi_nv_write(NV_KEY_SLE_LOCAL_NAME, lname, strlen(lname)); 
    }

    char cname[20] = {0};
    if (httpd_post_parse(payload, "cname", cname) == 0)
    {
        printf("child name: %s\r\n", cname);
        sle_set_server_name(cname);                                 
        uapi_nv_write(NV_KEY_SLE_CHILD_NAME, cname, strlen(cname)); 
    }

    pbuf_free(p);

    return ERR_OK;
}

void httpd_post_finished(void *connection, char *response_uri, uint16_t response_uri_len)
{
    strlcpy(response_uri, "/index.html", response_uri_len);
}

static u16_t httpd_ssi_handler(const char *ssi_tag_name, char *pcInsert, int iInsertLen)
{
    
    if (strcmp(ssi_tag_name, "lname") == 0) 
    {
        snprintf(pcInsert, iInsertLen, "%s", sle_get_announce_name());
    }
    else if (strcmp(ssi_tag_name, "cname") == 0) 
    {
        snprintf(pcInsert, iInsertLen, "%s", sle_get_server_name());
    }
    else
    {
        return HTTPD_SSI_TAG_UNKNOWN;
    }

    return strlen(pcInsert);
}

void ssi_handler_init(void)
{
    http_set_ssi_handler(httpd_ssi_handler, NULL, 0);
}
